﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using InfFront.UICore;

namespace InfFront.InfoSources.Base
{
    internal interface ICallbackMessage
    {
        void Proceed();
    }

    /// <summary>
    /// ICallbackMessage batcher
    /// use it to delay the callback execution diring the event handling
    /// </summary>
    internal class CallbackMessageBatch: IDisposable
    {
        private InfoSource rootSource;
        private CallbackMessageBatch prevBatch;
        private List<ICallbackMessage> messages;

        public CallbackMessageBatch(InfoSource rootSource)
        {
            this.rootSource = rootSource;
            this.prevBatch = rootSource.SetMessageBatch(this);
        }

        public void Add(ICallbackMessage message)
        {
            lock (this)
            {
                if (messages == null)
                    messages = new List<ICallbackMessage>();
                messages.Add(message);
            }
        }

        public void Dispose()
        {
            rootSource.SetMessageBatch(prevBatch);
            if (messages != null)
            {
                foreach (var message in messages)
                    rootSource.DispatchMessage(message);
            }
        }
    }

    internal abstract class InfoSourceMessage : ICallbackMessage
    {
        public InfoSource Source { get; set; }

        protected abstract void SendToCallbacks(IInfoSourceCallbacks cback);

        #region ICallbackMessage Members

        void ICallbackMessage.Proceed()
        {
            foreach (var cback in Source.Callbacks)
                SendToCallbacks(cback);
        }

        #endregion
    }

    /// <summary>
    /// InfoSource refresh message parameters
    /// </summary>
    internal class InfoSourceEntryRefreshMessage : InfoSourceMessage
    {
        public IInfoEntry Entry { get; set; }

        protected override void SendToCallbacks(IInfoSourceCallbacks cback)
        {
            cback.OnSourceEntryRefreshed(Entry);
        }
    }

    /// <summary>
    /// InfoSource refresh message parameters
    /// </summary>
    internal class InfoSourceRebuildMessage : InfoSourceMessage
    {
        protected override void SendToCallbacks(IInfoSourceCallbacks cback)
        {
            cback.OnSourceRebuilt();
        }
    }

    /// <summary>
    /// InfoSource edit entry message parameters
    /// </summary>
    internal class InfoSourceEditEntryMessage : InfoSourceMessage
    {
        public IInfoEntry Entry { get; set; }

        protected override void SendToCallbacks(IInfoSourceCallbacks cback)
        {
            cback.BeginEntryEdit(Entry);
        }
    }

    /// <summary>
    /// InfoSource edit entry message parameters
    /// </summary>
    internal class InfoSourceCreateEntryMessage : InfoSourceMessage
    {
        public IInfoEntry Entry { get; set; }

        protected override void SendToCallbacks(IInfoSourceCallbacks cback)
        {
            cback.BeginEntryCreate(Entry);
        }
    }
}
